﻿#region Namespace References

using System;
using System.Windows.Forms;
using DynConDevCorp.OpenArch.SmartData.Core;
using DynConDevCorp.OpenArch.SmartData.Core.EntityTypeLevel;
using DynConDevCorp.OpenArch.SmartData.Interfaces;
using DynConDevCorp.OpenArch.SmartData.Interfaces.Attributes;
using DynConDevCorp.OpenArch.SmartData.Interfaces.EventArgClasses;

#endregion

namespace SimpleWinForms
{
    public partial class Form1 : Form
    {
        #region Constructors

        public Form1()
        {
            InitializeComponent();
            m_TestField = new SmartField<long>();
            m_TestField.Value = 0;
            string test = m_TestField.DisplayValue;
            smartControl1.BoundSmartField = m_TestField;

            m_EchoField = new SmartField<string>();
            smartControl2.BoundSmartField = m_EchoField;
            smartControl3.BoundSmartField = m_EchoField;
            smartControl4.BoundSmartField = m_EchoField;
        }

        class TestEntity : SmartEntity
        {
            private Form1 MyForm { get; set; }
            public TestEntity(Form1 form)
            {
                MyForm = form;
            }

            [AutoField]
            public ISmartField<decimal> MemberField { get; private set; }
            [AutoField]
            public ISmartField<decimal> OtherField { get; private set; }
        }

        #endregion

        #region Public Instance Properties

        public ISmartField<long> m_TestField { get; set; }
        public ISmartField<string> m_EchoField { get; set; }

        #endregion

        class ParentEntity : SmartEntity
        {
            private Form1 MyForm { get; set; }
            public ParentEntity(Form1 form)
            {
                MyForm = form;
                OwnedTestEntity = new TestEntity(MyForm);
                LinkedTestEntity.LinkedEntity = OwnedTestEntity;
                RegisterField("OwnedTestEntity", OwnedTestEntity);
            }
            [AutoField(AutoCreate = false)]
            public TestEntity OwnedTestEntity { get; private set; }
 
            [AutoField]
            public SmartEntityLink<TestEntity> LinkedTestEntity { get; private set; }

        }
        class ParentEntity2 : SmartEntity
        {
            private Form1 MyForm { get; set;  }
            public ParentEntity2(Form1 form)
            {
                MyForm = form;
                ChildEntity.LinkedEntity = new ParentEntity(MyForm);
                RegisterFieldEffectForType<decimal>("ChildEntity.OwnedTestEntity.MemberField", Embedded_TypeLevel_Effect);
                ChildEntity.AddFieldEffect<decimal>("OwnedTestEntity.MemberField", Embedded_InstanceLevel_Effect);
                ChildEntity.AddFieldEffect<decimal>("LinkedTestEntity.MemberField", Embedded_LinkedInstanceLevel_Effect);
            }
            [AutoField]
            public SmartEntityLink<ParentEntity> ChildEntity { get; private set; }

            void Embedded_TypeLevel_Effect(object sender, ValueChangedEventArgs<decimal> e)
            {
                MyForm.RecordEvent(this, "Embedded_TypeLevel_Effect", sender, e);
            }

            void Embedded_InstanceLevel_Effect(object sender, ValueChangedEventArgs<decimal> e)
            {
                MyForm.RecordEvent(this, "Embedded_InstanceLevel_Effect", sender, e);
            }

            void Embedded_LinkedInstanceLevel_Effect(object sender, ValueChangedEventArgs<decimal> e)
            {
                MyForm.RecordEvent(this, "Embedded_LinkedInstanceLevel_Effect", sender, e);
            }

        }

        #region Private Instance Methods

        private DateTime m_StartTime;
        private void button1_Click(object sender, EventArgs e)
        {
            lbEffects.Items.Clear();
            m_StartTime = DateTime.Now;


            SmartEntityTypeLevelLibrary.Global.RegisterFieldEffectForType<decimal>(typeof(TestEntity), "MemberField", EntityLevel_Effect);
            SmartEntityTypeLevelLibrary.Global.RegisterFieldEffectForType<decimal>(typeof(ParentEntity), "OwnedTestEntity.MemberField", MidLevel_Effect);
            SmartEntityTypeLevelLibrary.Global.RegisterFieldEffectForType<decimal>(typeof(ParentEntity2), "ChildEntity.OwnedTestEntity.MemberField", ParentLevel_Type_Effect);
         
            
            ParentEntity2 newEntity = new ParentEntity2(this);

            newEntity.AddFieldEffect<decimal>("ChildEntity.OwnedTestEntity.MemberField", ParentLevel_Instance_Effect);

            // newEntity.RegisterFieldEffectForType(newEffect);
            TestEntity temp = newEntity.ChildEntity["OwnedTestEntity"] as TestEntity;
            temp.MemberField.Value = 123;
        }

        void ParentLevel_Instance_Effect(object sender, ValueChangedEventArgs<decimal> e)
        {
            RecordEvent(this, "ParentLevel_Instance_Effect", sender, e);
        }

        void ParentLevel_Type_Effect(object sender, ValueChangedEventArgs<decimal> e)
        {
            RecordEvent(this, "ParentLevel_Type_Effect", sender, e);
        }

        void MidLevel_Effect(object sender, ValueChangedEventArgs<decimal> e)
        {
            RecordEvent(this, "MidLevel_Effect", sender, e);
        }

        void EntityLevel_Effect(object sender, ValueChangedEventArgs<decimal> e)
        {
            RecordEvent(this, "EntityLevel_Effect", sender, e);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            timer1.Enabled ^= true;     // Toggle State..
        }

        #endregion

        private void timer1_Tick(object sender, EventArgs e)
        {
            TimeSpan elapsed = DateTime.Now - m_StartTime;
            long uS = (long) (1000 * elapsed.TotalMilliseconds);
            m_TestField.Value = uS;
        }

        public void RecordEvent(object instance, string handlerName, object sender, ValueChangedEventArgs<decimal> e)
        {
            string msg = String.Format("{0}\t\t\t{1}:{2}\t\t\t{3}", instance.GetType().Name, sender.GetType().Name, e.FieldName, handlerName);
            lbEffects.Items.Add(msg);
        }
    }
}